package com.devilvan.betrice.poetry.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devilvan.betrice.common.BetriceResultCode;
import com.devilvan.betrice.common.BetriceResultVo;
import com.devilvan.betrice.poetry.constant.PoetryConstant;
import com.devilvan.betrice.poetry.dto.PoetryKeywordDto;
import com.devilvan.betrice.poetry.mapper.PoetryDetailMapper;
import com.devilvan.betrice.poetry.po.PoetryDetailPo;
import com.devilvan.betrice.poetry.po.PoetryHeaderPo;
import com.devilvan.betrice.poetry.po.PoetryKeywordPo;
import com.devilvan.betrice.poetry.repository.PoetryDetailRepository;
import com.devilvan.betrice.poetry.repository.PoetryHeaderRepository;
import com.devilvan.betrice.poetry.service.PoetryKeywordService;
import com.devilvan.betrice.poetry.mapper.PoetryKeywordMapper;
import com.devilvan.betrice.poetry.repository.PoetryKeywordRepository;
import com.devilvan.betrice.request.component.JsoupComponent;
import com.devilvan.betrice.util.UEmpty;
import com.devilvan.betrice.util.UString;
import com.devilvan.betrice.util.UCopy;
import lombok.extern.log4j.Log4j2;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Evad.Wu
 * @Description 古诗文网-关键字分类信息表 业务逻辑类
 * @date 2022-11-29
 */
@Log4j2
@Service
public class PoetryKeywordServiceImpl extends ServiceImpl<PoetryKeywordMapper, PoetryKeywordPo> implements PoetryKeywordService {
    @Resource(name = "jsoupComponent")
    private JsoupComponent jsoupComponent;
    @Resource(name = "transactionTemplate")
    private TransactionTemplate transactionTemplate;

    @Resource(name = "poetryKeywordRepository")
    private PoetryKeywordRepository poetryKeywordRepository;
    @Resource(name = "poetryHeaderRepository")
    private PoetryHeaderRepository poetryHeaderRepository;
    @Resource(name = "poetryDetailRepository")
    private PoetryDetailRepository poetryDetailRepository;
    @Resource(name = "poetryKeywordMapper")
    private PoetryKeywordMapper poetryKeywordMapper;
    @Resource(name = "poetryDetailMapper")
    private PoetryDetailMapper poetryDetailMapper;

    @Override
    public PoetryKeywordPo saveUpdate(PoetryKeywordDto poetryKeywordDto) {
        PoetryKeywordPo poetryKeywordPo = new PoetryKeywordPo();
        UCopy.fullCopy(poetryKeywordDto, poetryKeywordPo);
        return poetryKeywordRepository.save(poetryKeywordPo);
    }

    @Override
    public List<PoetryKeywordPo> saveUpdateBatch(List<PoetryKeywordDto> list) {
        List<PoetryKeywordPo> poetryKeywordPoList = UCopy.fullCopyCollections(list, PoetryKeywordPo.class);
        return poetryKeywordRepository.saveAll(poetryKeywordPoList);
    }

    @Override
    public BetriceResultVo<PoetryKeywordPo> doPoetryKeywordCrawler() {
        BetriceResultVo<PoetryKeywordPo> betriceResultVo = new BetriceResultVo<>();
        Element body = jsoupComponent.getBody(PoetryConstant.GUSHIWEN_SHIWEN_URL);
        Elements keywordElements = body.select("div.sright>a");
        List<PoetryKeywordDto> poetryKeywordDtoList = new ArrayList<>();
        for (Element keywordElement : keywordElements) {
            PoetryKeywordDto poetryKeywordDto = new PoetryKeywordDto();
            String keyword = keywordElement.text();
            String keywordUrl = PoetryConstant.GUSHIWEN_DEFAULT_URL + keywordElement.attr("href");
            poetryKeywordDto.setKeyword(keyword);
            poetryKeywordDto.setKeywordUrl(keywordUrl);
            poetryKeywordDtoList.add(poetryKeywordDto);
        }
        // 由于网站上的keyword有重复的情况，需要去重
        poetryKeywordDtoList = poetryKeywordDtoList.stream().distinct().toList();
        try {
            this.saveUpdateBatch(poetryKeywordDtoList);
            betriceResultVo.result(BetriceResultCode.SUCCESS_200, "操作成功！");
        } catch (Exception e) {
            e.printStackTrace();
            betriceResultVo.result(BetriceResultCode.FAILED_500, "操作失败！");
        }
        return betriceResultVo;
    }

    @Override
    public void doPoetryKeywordParser() {
        Element body = null;
        try {
            body = Jsoup.parse(new File(PoetryConstant.RESOURCE_PATH), "UTF-8").body();
        } catch (IOException e) {
            e.printStackTrace();
        }
        assert body != null;
        Elements keywordElements = body.select("div.sright>a");
        List<PoetryKeywordDto> poetryKeywordDtoList = new ArrayList<>();
        for (Element keywordElement : keywordElements) {
            PoetryKeywordDto poetryKeywordDto = new PoetryKeywordDto();
            String keyword = keywordElement.text();
            String keywordUrl = PoetryConstant.GUSHIWEN_DEFAULT_URL + keywordElement.attr("href");
            poetryKeywordDto.setKeyword(keyword);
            poetryKeywordDto.setKeywordUrl(keywordUrl);
            poetryKeywordDtoList.add(poetryKeywordDto);
        }
        // 由于网站上的keyword有重复的情况，需要去重
        poetryKeywordDtoList = poetryKeywordDtoList.stream().distinct().toList();
        this.saveUpdateBatch(poetryKeywordDtoList);
    }

    @Override
    public BetriceResultVo<PoetryKeywordPo> doPoetryByKeyword(String keyword) {
        BetriceResultVo<PoetryKeywordPo> betriceResultVo = new BetriceResultVo<>();
        betriceResultVo.result(BetriceResultCode.FAILED_500, "操作失败！");
        // 构造一个带参数的get请求url
        Map<String, Object> params = new HashMap<>(2);
        params.put("value", keyword);
        params.put("valuej", String.valueOf(keyword.charAt(0)));
        String url = UString.generateHttpParamUrl(PoetryConstant.GUSHIWEN_SEARCH_URL, params);
        log.info("URL：" + url);
        // 初始化header的referer
        Map<String, String> headers = new HashMap<>(1);
        headers.put("referer", url);
        // 记录一条keyword信息
        PoetryKeywordPo poetryKeywordPo = new PoetryKeywordPo();
        poetryKeywordPo.setKeyword(keyword);
        poetryKeywordPo.setKeywordUrl(url);
        poetryKeywordPo.setIsCrawl(true);
        List<PoetryHeaderPo> poetryHeaderPoList = new ArrayList<>();
        List<PoetryDetailPo> poetryDetailPoList = new ArrayList<>();
        while (true) {
            Element body = jsoupComponent.getBody(url, headers);
            Elements contentList = body.select("div.left>div.sons>div.cont");
            for (Element content : contentList) {
                // 获取标题
                Elements titleElem = content.select("p:nth-child(2)>a");
                String title = titleElem.text();
                // 获取作者、朝代
                String authorDynasty = content.select("p.source").text();
                String[] split = authorDynasty.split("〔");
                String author = null;
                String dynasty = null;
                if (split.length == 1) {
                    author = split[0];
                } else if (split.length == 2) {
                    author = split[0];
                    dynasty = split[1].replace("〕", "");
                }
                String detailUrl = PoetryConstant.GUSHIWEN_DEFAULT_URL + titleElem.attr("href");
                PoetryHeaderPo poetryHeaderPo = new PoetryHeaderPo();
                poetryHeaderPo.setKeyword(keyword);
                poetryHeaderPo.setTitle(title);
                poetryHeaderPo.setAuthor(author);
                poetryHeaderPo.setDynasty(dynasty);
                poetryHeaderPo.setDetailUrl(detailUrl);
                poetryHeaderPoList.add(poetryHeaderPo);
                Integer isExsist = poetryDetailMapper.findExsistByTitleAndAuthor(title, author);
                if (isExsist != 0) {
                    continue;
                }
                // 获取内容
                Elements htmlText = content.select("div.contson");
                String text = htmlText.text();
                String contentMd = htmlText.html();
                PoetryDetailPo poetryDetailPo = new PoetryDetailPo();
                poetryDetailPo.setTitle(title);
                poetryDetailPo.setAuthor(author);
                poetryDetailPo.setContent(text);
                poetryDetailPo.setContentMd(contentMd);
                poetryDetailPoList.add(poetryDetailPo);
            }
            // 下一页，若无则跳出循环
            String href = body.select("div.left>form#Form1>div.pagesright>a.amore").attr("href");
            if (UEmpty.isEmpty(href)) {
                break;
            }
            url = PoetryConstant.GUSHIWEN_DEFAULT_URL + href;
            String currentPageReferer = headers.get("referer");
            headers.put("referer", currentPageReferer);
        }
        transactionTemplate.execute(status -> {
            poetryKeywordRepository.save(poetryKeywordPo);
            poetryHeaderRepository.saveAll(poetryHeaderPoList);
            poetryDetailRepository.saveAll(poetryDetailPoList);
            return null;
        });
        betriceResultVo.result(BetriceResultCode.SUCCESS_200, "操作成功！", poetryKeywordPo);
        return betriceResultVo;
    }
}
